using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Xml;
using System.Web;
using System.IO;

using OrbitOne.Feed.Domain;
using OrbitOne.Feed.Interfaces;

namespace OrbitOne.Feed.Handlers {
    /// <summary>
    /// Writes atom formatted xml in the http output stream
    /// </summary>
    internal class ATOMWriter : AbstractWriter {
        #region Members :
        const String _dateTimeFormat = "yyyy-MM-ddThh:mm:ssZ";
        const String _namespace = "http://www.w3.org/2005/Atom";
        #endregion Members
        #region Ctor's :
        public ATOMWriter(WebFeed webFeed) : base(webFeed) {
        }
        #endregion Ctor's
        #region Methods :
        #region Implementation Abstract methods :
        /// <summary>
        /// Writes the actual feed in to the Http output stream.
        /// This method must be implemented by specific Writers like the Atom, RSS or podcast writers.
        /// </summary>
        /// <param name="webFeed">The web feed.</param>
        public override void WriteFeed() {
            this.WriteFeedRootElement(); 
            this.WriteRootAttributes();
            this.WriteFeedId();
            this.WriteFeedDescription();
            this.WriteFeedSelfUrl();
            this.WriteFeedUrl();
            this.WriteFeedTitle();
            this.WriteFeedLastUpdated();
            this.WriteCopyright();
            this.WriteFeedAuthor();
            _writer.WriteEndElement();
             foreach (Topic topic in webFeed.Topics) {
                WriteTopic(topic);
             }
            _writer.WriteEndElement();
            _writer.Flush();
        }
        /// <summary>
        /// Writes an Id identifiying this feed.
        /// </summary>
        private void WriteFeedId() {
            base.WriteElementValue("id", webFeed.Url.ToString());
        }
        /// <summary>
        /// Writes the root element
        /// </summary>
        protected override void WriteFeedRootElement() {
            _writer.WriteStartElement("feed");
        }
        /// <summary>
        /// Writes the copyright text.
        /// </summary>
        protected override void WriteCopyright() {
            base.WriteElementValue("rights", webFeed.Copyright);
        }
        /// <summary>
        /// Writes the last update date time of the feed
        /// </summary>
        protected override void WriteFeedLastUpdated() {
            base.WriteElementValue("updated", DateTime.Now.ToString(_dateTimeFormat));
        }
        /// <summary>
        /// Writes the feed description to the Http Ouput stream.
        /// </summary>
        protected override void WriteFeedDescription() {
            base.WriteElementValue("subtitle", webFeed.Description);
        }
        /// <summary>
        /// Writes some attributes to the root element e.g version of the feed format, namespaces, ...
        /// </summary>
        protected override void WriteRootAttributes() {
            WriteAttributeValue("xmlns", _namespace);
            WriteAttributeValue("xml:lang", webFeed.Culture.Name.ToLower());
        }
        /// <summary>
        /// Writes the link of the web feed
        /// </summary>
        protected override void WriteFeedUrl() {
            if (webFeed.HasUrl) {
                _writer.WriteStartElement("link");
                WriteAttributeValue("href", webFeed.Url.ToString());
                _writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the self link of the web feed
        /// </summary>
        private void WriteFeedSelfUrl() {
            if (webFeed.HasUrl) {
                _writer.WriteStartElement("link");
                WriteAttributeValue("href", new Uri(HttpContext.Current.Request.Url.AbsoluteUri).ToString());
                WriteAttributeValue("rel", "self");
                _writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes a single topic info into the Http Output stream.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopic(Topic topic) {
            _writer.WriteStartElement("entry");
            WriteTopicAuthor(topic);
            base.WriteElementValue("title", topic.Title);
            WriteTopicIdentification(topic);
            WriteTopicPublishDateTime(topic);

            if (topic.HasUrl) {
                _writer.WriteStartElement("link");
                WriteAttributeValue("href", topic.Url.ToString());
                _writer.WriteEndElement();
            }
            WriteTopicCategories(topic);
            WriteTopicContent(topic);
            base.WriteElementValue("summary", topic.Description);
            _writer.WriteEndElement();
        }
        /// <summary>
        /// Writes the publish date time or the last modified date of a topic.
        /// </summary>
        /// <param name="topic">The topic.</param>
        protected override void WriteTopicPublishDateTime(Topic topic) {
            base.WriteElementValue("updated", topic.PublishDateTime.ToString(_dateTimeFormat));
        }
        /// <summary>
        /// Writes an idenfitier for a topic, to allow the feed reader to differentiate between topics,
        /// and flag topics as read.
        /// </summary>
        /// <param name="topic"></param>
        protected override void WriteTopicIdentification(Topic topic) {
            base.WriteElementValue("id", topic.Url.ToString());
        }
        /// <summary>
        /// Writes the topic author info like name and email to the Http Output stream.
        /// </summary>
        /// <param name="topic"></param>
        protected override void WriteTopicAuthor(Topic topic) {
            if (topic.HasAuthor) {
                _writer.WriteStartElement("author");
                base.WriteElementValue("name", topic.Author.Name);
                base.WriteElementValue("email", topic.Author.Email);
                _writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the content of a topic to the Http Output stream
        /// </summary>
        /// <param name="topic"></param>
        protected override void WriteTopicContent(Topic topic) {
            if (topic.HasContent) {
                base._writer.WriteStartElement("content");
                base.WriteAttributeValue("type", "text");
                //base.WriteAttributeValue("src", topic.Content.Url.ToString());
                base._writer.WriteValue(topic.Description);
                base._writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Writes the associated categories of a topic out to the Http Output stream.
        /// </summary>
        /// <param name="topic"></param>
        protected override void WriteTopicCategories(Topic topic) {
            foreach (Category category in topic.Categories) {
                _writer.WriteStartElement("category");
                WriteAttributeValue("term", category.Name);
                _writer.WriteEndElement();
            }
        }
        /// <summary>
        /// Write the feed author to the Http Output Stream
        /// </summary>
        protected override void WriteFeedAuthor() {
            if (webFeed.HasAuthor) {
                _writer.WriteStartElement("author");
                base.WriteElementValue("name", webFeed.Author.Name);
                base.WriteElementValue("email", webFeed.Author.Email);
            }
        }
        /// <summary>
        /// Writes the feed's title to the Http Ouput stream.
        /// </summary>
        protected override void WriteFeedTitle() {
            base.WriteElementValue("title", webFeed.Title);
        }
        #endregion Implementation Abstract methods 
        #endregion Methods
    }
}
